package se.devoteam.nexus.ldap;

import java.io.File;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Set;

import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;

import org.apache.directory.server.configuration.MutableServerStartupConfiguration;
import org.apache.directory.server.core.configuration.MutablePartitionConfiguration;
import org.apache.directory.server.unit.AbstractServerTest;

/**
 * Create and set up an LDAP test server which is used for tests.
 */
public class LdapTestServer {
	
	private static final String SERVER_WORKING_DIRECTORY = "target/apacheds-work";
	
	private InternalLdapServer wrappedService = new InternalLdapServer();
	
	private class InternalLdapServer extends AbstractServerTest {
		@Override
		public void setUp() throws Exception {
			super.setUp();
		}
		
		@Override
		public void tearDown() throws Exception {
	    	super.tearDown();
	    }
		
		@Override
		public void importLdif(InputStream in) throws NamingException {
			super.importLdif(in);
		}
		
		public MutableServerStartupConfiguration getConfiguration() {
			return super.configuration;
		}
	}
	
	/**
	 * Initialize the server.
	 */
	public void setUp(String[] ldifFiles) throws Exception {
		// Create partition
		MutablePartitionConfiguration pcfg = new MutablePartitionConfiguration();
		pcfg.setName("dn");
		pcfg.setSuffix("dc=example,dc=devoteam,dc=se");

		// Create some indices
		Set<String> indexedAttrs = new HashSet<String>();
		indexedAttrs.add("objectClass");
		indexedAttrs.add("o");
		pcfg.setIndexedAttributes(indexedAttrs);

		// Create a first entry associated to the partition
		Attributes attrs = new BasicAttributes(true);

		// First, the objectClass attribute
		Attribute attr = new BasicAttribute("objectClass");
		attr.add("top");
		attr.add("domain");
		attrs.put(attr);

		// Associate this entry to the partition
		pcfg.setContextEntry(attrs);

		// As we can create more than one partition, we must store
		// each created partition in a Set before initialization
		Set<MutablePartitionConfiguration> pcfgs = new HashSet<MutablePartitionConfiguration>();
		pcfgs.add(pcfg);

		this.wrappedService.getConfiguration().setContextPartitionConfigurations(pcfgs);

		// Create a working directory
		File workingDirectory = new File(SERVER_WORKING_DIRECTORY);
		this.wrappedService.getConfiguration().setWorkingDirectory(workingDirectory);

		this.wrappedService.setUp();

		// Import all LDIF files
		for (String str : ldifFiles) {
			InputStream is = null;
			try {
				is = this.getClass().getResourceAsStream(str);
				this.wrappedService.importLdif(is);
			} catch (Exception e) {
				tearDown(); // clean up
				throw e;
			} finally {
				if (is != null) {
					try {
						is.close();
					} catch (Exception e) {
						// do nothing
					}
				}
			}
		}
	}

	/**
	 * Shut down the server.
	 */
	public void tearDown() throws Exception {
		this.wrappedService.tearDown();
	}
}
